# We treat transforms as 4x4 matrices stored as 2d numpy ndarrays.
# Note that OpenGL assumes column major order, but numpy defaults to row
# major, so we have to force it to column major instead.
# Robert Bridson
# Released under the GPLv3

from math import sin, cos, tan
import numpy

def identity():
    return numpy.array([[1, 0, 0, 0],
                        [0, 1, 0, 0],
                        [0, 0, 1, 0],
                        [0, 0, 0, 1]], dtype='float32')
def translate(x):
    return numpy.array([[1, 0, 0, x[0]],
                        [0, 1, 0, x[1]],
                        [0, 0, 1, x[2]],
                        [0, 0, 0,   1 ]], dtype='float32')
    
def translate_x(a):
    return numpy.array([[1, 0, 0, a],
                        [0, 1, 0, 0],
                        [0, 0, 1, 0],
                        [0, 0, 0, 1]], dtype='float32')
def translate_y(a):
    return numpy.array([[1, 0, 0, 0],
                        [0, 1, 0, a],
                        [0, 0, 1, 0],
                        [0, 0, 0, 1]], dtype='float32')
    
def translate_z(a):
    return numpy.array([[1, 0, 0, 0],
                        [0, 1, 0, 0],
                        [0, 0, 1, a],
                        [0, 0, 0, 1]], dtype='float32')

def rotate_x(theta):
    c = cos(theta)
    s = sin(theta)
    return numpy.array([[1, 0,  0, 0],
                        [0, c, -s, 0],
                        [0, s,  c, 0],
                        [0, 0,  0, 1]], dtype='float32')

def rotate_y(theta):
    c = cos(theta)
    s = sin(theta)
    return numpy.array([[ c, 0, s, 0],
                        [ 0, 1, 0, 0],
                        [-s, 0, c, 0],
                        [ 0, 0, 0, 1]], dtype='float32')

def rotate_z(theta):
    c = cos(theta)
    s = sin(theta)
    return numpy.array([[c, -s, 0, 0],
                        [s,  c, 0, 0],
                        [0,  0, 1, 0],
                        [0,  0, 0, 1]], dtype='float32')

def scaleHiDef(s0, s1, s2):
    return numpy.array([[s0,  0,  0, 0],
                        [ 0, s1,  0, 0],
                        [ 0,  0, s2, 0],
                        [ 0,  0,  0, 1]], dtype='float32')

def perspective(fovy, aspect, znear, zfar):
    f = 1.0/tan(0.5*fovy)
    a = (zfar+znear)/(znear-zfar)
    b = (2*zfar*znear)/(znear-zfar)
    return numpy.array([[f/aspect, 0,  0, 0],
                        [       0, f,  0, 0],
                        [       0, 0,  a, b],
                        [       0, 0, -1, 0]], dtype='float32')

def compose(*args):
    "Multiply together any number of transforms in order"
    t = identity()
    for s in args:
        t = numpy.dot(t, s)
    return t

def composeTransformList(transformList):
    t = identity()
    for cur in transformList:
        t = numpy.dot(t, cur)
    return t

